package com.myzl.coal.mongo.component;

import com.alibaba.fastjson2.JSONObject;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author cew
 * @date 2023年4月14日11:28:51
 */
@Component
public class MongoComponent {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 插入单条数据 效率高，但是id重复会抛出异常
     * @param o 单个任意对象参数
     * @return 参数对象
     */
    public <T> T insertOne(T o){
        return mongoTemplate.insert(o);
    }

    /**
     * 插入单条数据 效率高，但是id重复会抛出异常
     * @param o 单个任意对象参数
     * @param collectionName 集合名称
     * @return 参数对象
     */
    public <T> T insertOne(T o,String collectionName){
        return mongoTemplate.insert(o,collectionName);
    }

    /**
     * 插入单条数据 id不重复新增，重复根据id修改
     * @param o 单个任意对象参数
     * @return 参数对象
     */
    public <T> T saveOrUpdate(T o){
        return mongoTemplate.save(o);
    }

    /**
     * 插入单条数据 id不重复新增，重复根据id修改
     * @param o 单个任意对象参数
     * @param collectionName 集合名称
     * @return 参数对象
     */
    public <T> T saveOrUpdate(T o,String collectionName){
        return mongoTemplate.save(o,collectionName);
    }

    /**
     * 批量保存
     * @param list 数据集合 效率高，但是id重复会抛出异常
     * @return 数据集合
     */
    public <T> List<T> saveBatch(List<T> list){
        Collection<T> result = mongoTemplate.insertAll(list);
        return new ArrayList<>(result);
    }

    /**
     * 批量保存
     * @param list 数据集合 效率高，但是id重复会抛出异常
     * @param collectionName 集合名称
     * @return 数据集合
     */
    public <T> List<T> saveBatch(List<T> list,String collectionName){
        Collection<T> result = mongoTemplate.insert(list, collectionName);
        return new ArrayList<>(result);
    }

    /**
     * 批量保存
     * @param list 数据集合 效率高，但是id重复会抛出异常
     * @param entityClass 集合class
     * @return 数据集合
     */
    public <T> List<T> saveBatch(List<T> list,Class<T> entityClass){
        Collection<T> result = mongoTemplate.insert(list, entityClass);
        return new ArrayList<>(result);
    }

    /**
     * 批量保存
     * @param list 数据集合
     * @return 数据集合
     */
    public <T> List<T> saveOrUpdateBatch(List<T> list){
        List<T> ts = new ArrayList<>();
        for (T o : list) {
            T t = mongoTemplate.save(o);
            ts.add(t);
        }
        return ts;
    }

    /**
     * 批量保存
     * @param list 数据集合
     * @param collectionName 集合名称
     * @return 数据集合
     */
    public <T> List<T> saveOrUpdateBatch(List<T> list,String collectionName){
        List<T> ts = new ArrayList<>();
        for (T o : list) {
            T t = mongoTemplate.save(o,collectionName);
            ts.add(t);
        }
        return ts;
    }

    /**
     * 根据对象id删除，只需要赋值对象id,否则会抛出异常
     * @param o 数据实体
     */
    public Long removeById(Object o){
        DeleteResult remove = mongoTemplate.remove(o);
        return remove.getDeletedCount();
    }

    /**
     * 清空数据
     * @param o 数据实体
     * @param collectionName 集合名称
     * @return 删除行数
     */
    public Long removeById(Object o,String collectionName){
        DeleteResult remove = mongoTemplate.remove(o, collectionName);
        return remove.getDeletedCount();
    }

    /**
     * 根据条件删除
     * @param criteria 删除条件
     * @param collectionName 集合名称
     * @return 删除行数
     */
    public Long remove(Criteria criteria,String collectionName){
        Query query = Query.query(criteria);
        DeleteResult remove = mongoTemplate.remove(query, collectionName);
        return remove.getDeletedCount();
    }

    /**
     * 根据条件删除
     * @param criteria 删除条件
     * @param sort 排序方式（升序、降序）
     *             构建方式为 Sort.by(Sort.Order.asc(columnName),Sort.Order.desc(columnName))
     * @param collectionName 集合名称
     * @return 删除行数
     */
    public Long remove(Criteria criteria,Sort sort,String collectionName){
        Query query = Query.query(criteria).with(sort);
        DeleteResult remove = mongoTemplate.remove(query, collectionName);
        return remove.getDeletedCount();
    }

    /**
     * 根据条件删除
     * @param criteria 删除条件
     * @param entityClass 实体类Class
     * @return 删除行数
     */
    public Long remove(Criteria criteria,Class<?> entityClass){
        Query query = Query.query(criteria);
        DeleteResult remove = mongoTemplate.remove(query, entityClass);
        return remove.getDeletedCount();
    }

    /**
     * 根据条件删除
     * @param criteria 删除条件
     * @param sort 排序方式（升序、降序）
     *             构建方式为 Sort.by(Sort.Order.asc(columnName),Sort.Order.desc(columnName))
     * @param entityClass 实体类Class
     * @return 删除行数
     */
    public Long remove(Criteria criteria,Sort sort,Class<?> entityClass){
        Query query = Query.query(criteria).with(sort);
        DeleteResult remove = mongoTemplate.remove(query, entityClass);
        return remove.getDeletedCount();
    }

    /**
     * 清空表
     * @param collectionName 集合名称
     * @return 删除行数
     */
    public Long removeAll(String collectionName){
        DeleteResult remove = mongoTemplate.remove(new Query(), collectionName);
        return remove.getDeletedCount();
    }

    /**
     * 清空表
     * @param entityClass 实体类Class
     * @return 删除行数
     */
    public Long removeAll(Class<?> entityClass){
        DeleteResult remove = mongoTemplate.remove(new Query(), entityClass);
        return remove.getDeletedCount();
    }

    /**
     * 修改匹配的第一条
     * @param criteria 匹配条件
     * @param update 修改参数  构建方式：new Update().set(key,value)
     * @param entityClass 实体类Class
     * @return 修改的行数
     */
    public Long updateFirst(Criteria criteria, Update update, Class<?> entityClass) {
        Query query = Query.query(criteria);
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, entityClass);
        return updateResult.getModifiedCount();
    }

    /**
     * 修改匹配的第一条
     * @param criteria 匹配条件
     * @param update 修改参数  构建方式：new Update().set(key,value)
     * @param collectionName 集合名字
     * @return 修改的行数
     */
    public Long updateFirst(Criteria criteria, Update update, String collectionName) {
        Query query = Query.query(criteria);
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, collectionName);
        return updateResult.getModifiedCount();
    }

    /**
     * 修改匹配的第一条
     * @param criteria 匹配条件
     * @param update 修改参数  构建方式：new Update().set(key,value)
     * @param entityClass 实体类Class
     * @param collectionName 集合名字
     * @return 修改的行数
     */
    public Long updateFirst(Criteria criteria, Update update, Class<?> entityClass, String collectionName) {
        Query query = Query.query(criteria);
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, entityClass, collectionName);
        return updateResult.getModifiedCount();
    }

    /**
     * 修改匹配的全部数据
     * @param criteria 匹配条件
     * @param update 修改参数  构建方式：new Update().set(key,value)
     * @param entityClass 实体类Class
     * @return 修改的行数
     */
    public Long updateMulti(Criteria criteria,  Update update, Class<?> entityClass){
        Query query = Query.query(criteria);
        UpdateResult updateResult = mongoTemplate.updateMulti(query, update, entityClass);
        return updateResult.getModifiedCount();
    }

    /**
     * 修改匹配的全部数据
     * @param criteria 匹配条件
     * @param update 修改参数  构建方式：new Update().set(key,value)
     * @param collectionName 集合名字
     * @return 修改的行数
     */
    public Long updateMulti(Criteria criteria,  Update update, String collectionName){
        Query query = Query.query(criteria);
        UpdateResult updateResult = mongoTemplate.updateMulti(query, update, collectionName);
        return updateResult.getModifiedCount();
    }

    /**
     * 修改匹配的全部数据
     * @param criteria 匹配条件
     * @param update 修改参数  构建方式：new Update().set(key,value)
     * @param entityClass 实体类Class
     * @param collectionName 集合名字
     * @return 修改的行数
     */
    public Long updateMulti(Criteria criteria,  Update update, Class<?> entityClass, String collectionName){
        Query query = Query.query(criteria);
        UpdateResult updateResult = mongoTemplate.updateMulti(query, update, entityClass, collectionName);
        return updateResult.getModifiedCount();
    }

    /**
     * 数量统计
     * @param collectionName 集合名称
     * @return 数量
     */
    public Long count(String collectionName){
        return mongoTemplate.count(new Query(),collectionName);
    }

    /**
     * 数量统计
     * @param criteria 查询条件
     * @param collectionName 集合名称
     * @return 数量
     */
    public Long count(Criteria criteria,String collectionName){
        Query query = Query.query(criteria);
        return mongoTemplate.count(query,collectionName);
    }
    /**
     * 数量统计
     * @param criteria 查询条件
     * @param sort 排序方式（升序、降序）
     *             构建方式为 Sort.by(Sort.Order.asc(columnName),Sort.Order.desc(columnName))
     * @param collectionName 集合名称
     * @return 数量
     */
    public Long count(Criteria criteria,Sort sort,String collectionName){
        Query query = Query.query(criteria).with(sort);
        return mongoTemplate.count(query,collectionName);
    }

    /**
     * 数量统计
     * @param entityClass 实体类Class
     * @return 数量
     */
    public Long count(Class<?> entityClass){
        return mongoTemplate.count(new Query(),entityClass);
    }

    /**
     * 数量统计
     * @param entityClass 实体类Class
     * @return 数量
     */
    public Long count(Criteria criteria,Class<?> entityClass){
        Query query = Query.query(criteria);
        return mongoTemplate.count(query,entityClass);
    }

    /**
     * 数量统计
     * @param criteria 查询条件
     * @param sort 排序方式（升序、降序）
     *             构建方式为 Sort.by(Sort.Order.asc(columnName),Sort.Order.desc(columnName))
     * @param entityClass 实体类Class
     * @return 数量
     */
    public Long count(Criteria criteria,Sort sort,Class<?> entityClass){
        Query query = Query.query(criteria).with(sort);
        return mongoTemplate.count(query,entityClass);
    }

    /**
     * 根据条件判断数据是否存在
     * @param criteria 判断条件
     * @param collectionName 集合名称
     * @return 结果
     */
    public boolean exists(Criteria criteria,String collectionName){
        Query query =Query.query(criteria);
        return mongoTemplate.exists(query,collectionName);
    }

    /**
     * 根据条件判断数据是否存在
     * @param criteria 判断条件
     * @param entityClass 实体类Class
     * @return 结果
     */
    public boolean exists(Criteria criteria,Class<?> entityClass){
        Query query =Query.query(criteria);
        return mongoTemplate.exists(query,entityClass);
    }

    /**
     * 通过id查询单条数据
     * @param id id
     * @param entityClass 实体类Class
     * @return 结果
     */
    public <T> T findOneById(String id,Class<T> entityClass){
        return mongoTemplate.findById(id, entityClass);
    }

    /**
     * 通过id查询单条数据
     * @param id id
     * @param entityClass 实体类Class
     * @return 结果
     */
    public <T> T findOneById(String id,Class<T> entityClass,String collectionName){
        return mongoTemplate.findById(id, entityClass,collectionName);
    }

    /**
     * 通过条件查询单条数据
     * @param criteria 查询条件
     * @param sort 排序条件
     * @param entityClass 实体类Class
     * @return 结果
     */
    public <T> T findOne(Criteria criteria, Sort sort, Class<T> entityClass){
        Query query = Query.query(criteria).with(sort).limit(1);
        return mongoTemplate.findOne(query, entityClass);
    }
    public <T> String findMax(Aggregation aggregation, Class<T> entityClass){
        final AggregationResults<String> aggregationResults = mongoTemplate.aggregate(aggregation, entityClass.getSimpleName(), String.class);
        List<String> mappedResults = aggregationResults.getMappedResults();
        if (CollectionUtils.isEmpty(mappedResults)){
            return "0";
        }
        String dataValueMax = JSONObject.parseObject(mappedResults.get(0)).getString("dataValueMax");
        return dataValueMax;
    }

    public <T> T findOne(Criteria criteria, Class<T> entityClass){
        Query query = Query.query(criteria);
        return mongoTemplate.findOne(query, entityClass);
    }

    /**
     * 通过条件查询单条数据
     * @param criteria 查询条件
     * @param entityClass 实体类Class
     * @param collectionName 集合名字
     * @return 结果
     */
    public <T> T findOne(Criteria criteria, Class<T> entityClass, String collectionName){
        Query query = Query.query(criteria);
        return mongoTemplate.findOne(query, entityClass,collectionName);
    }

    /**
     * 查询全部数据
     * @param entityClass 实体类Class
     * @return 结果集
     */
    public <T> List<T> findAll(Class<T> entityClass){
        return mongoTemplate.findAll(entityClass);
    }

    /**
     * 查询全部数据
     * @param entityClass 实体类Class
     * @param collectionName 集合名字
     * @return 结果集
     */
    public <T> List<T> findAll(Class<T> entityClass, String collectionName){
        return mongoTemplate.findAll(entityClass,collectionName);
    }


    /**
     * 自定义查询
     * @param criteria 查询条件
     * @param entityClass 实体类Class
     * @return 结果
     */
    public <T> List<T> selectList(Criteria criteria, Class<T> entityClass) {
        Query query = Query.query(criteria);
        return mongoTemplate.find(query, entityClass);
    }

    /**
     * 自定义查询，并限制返回条数
     * @param criteria 查询条件
     * @param limit 限制返回条数
     * @param entityClass 实体类Class
     * @return 结果
     */
    public <T> List<T> selectList(Criteria criteria, int limit, Class<T> entityClass) {
        Query query = Query.query(criteria).limit(limit);
        return mongoTemplate.find(query, entityClass);
    }

    /**
     * 自定义查询并排序
     * @param criteria 自定义查询条件
     * @param sort 自定义排序字段及方式
     * @param entityClass 实体类Class
     * @return 结果
     */
    public <T> List<T> selectList(Criteria criteria,Sort sort, Class<T> entityClass) {
        Query query = Query.query(criteria).with(sort);
        return mongoTemplate.find(query, entityClass);
    }

    /**
     * 自定义查询、排序、限制返回条数
     * @param criteria 查询条件
     * @param limit 限制返回条数
     * @param sort 自定义排序字段及方式
     * @param entityClass 实体类Class
     * @return 结果
     */
    public <T> List<T> selectList(Criteria criteria, int limit, Sort sort, Class<T> entityClass) {
        Query query = Query.query(criteria).limit(limit).with(sort);
        return mongoTemplate.find(query, entityClass);
    }

    /**
     * 查询分页数据
     * @param pageNum 页码 从第一页开始，不可传入比1小的数
     * @param pageSize 页大小，一页的数据
     * @param entityClass 实体类Class
     * @return 结果
     */
    public <T> List<T> findPage(int pageNum,int pageSize,Class<T> entityClass){
        Pageable pageable = PageRequest.of(pageNum-1, pageSize);
        Query query = Query.query(new Criteria()).with(pageable);
        return mongoTemplate.find(query, entityClass);
    }

    /**
     * 查询分页数据并排序
     * @param pageNum 页码 从第一页开始，不可传入比1小的数
     * @param pageSize 页大小，一页的数据
     * @param sort 排序字段及方式（升序、降序），可设置多个列
     * @param entityClass 实体类Class
     * @return 结果
     */
    public <T> List<T>  findPageSort(int pageNum,int pageSize,Sort sort,Class<T> entityClass){
        Pageable pageable = PageRequest.of(pageNum-1, pageSize,sort);
        Query query = Query.query(new Criteria()).with(pageable);
        return mongoTemplate.find(query, entityClass);
    }

    /**
     * 根据条件查询分页数据
     * @param criteria 查询条件
     * @param pageNum 页码
     * @param pageSize 页大小
     * @param entityClass 实体类Class
     * @return 结果
     */
    public <T> List<T> findPage(Criteria criteria,int pageNum,int pageSize,Class<T> entityClass){
        Pageable pageable = PageRequest.of(pageNum-1, pageSize);
        Query query = Query.query(criteria).with(pageable);
        return mongoTemplate.find(query, entityClass);
    }

    /**
     * 根据条件查询分页数据并排序
     * @param criteria 查询条件
     * @param pageNum 页码
     * @param pageSize 页大小
     * @param sort 排序字段及方式（升序、降序），可设置多个列
     * @param entityClass 实体类Class
     * @return 结果
     */
    public <T> List<T> findPage(Criteria criteria,int pageNum,int pageSize,Sort sort,Class<T> entityClass){
        Pageable pageable = PageRequest.of(pageNum-1, pageSize,sort);
        Query query = Query.query(criteria).with(pageable);
        return mongoTemplate.find(query, entityClass);
    }

}
